package com.atguigu.gmall.item.config;

import com.atguigu.gmall.common.cache.GmallCacheAspect;
import com.atguigu.gmall.common.config.ItemServiceRedissonConfig;
import feign.Logger;
import lombok.Data;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import java.util.UUID;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author lsj
 * @create 2021-08-18 20:03
 *
 *      工具类提取的所有自动配置类我们使用 @Import 即可
 *      导入自己的 GmallCacheAspect.class 分布式缓存切面
 *
 */
@Import({ItemServiceRedissonConfig.class, GmallCacheAspect.class})
//让 Spring Boot自己的RedisAutoConfiguration 配置完以后再启动我们的
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableAspectJAutoProxy  //开启切面功能
@Configuration
public class ItemConfig {

    @Bean // 查看feign的日志，需要和yaml中配置的feign日志一起使用
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
    /**
     * int corePoolSize,      8
     * int maximumPoolSize,   16
     * long keepAliveTime,
     * TimeUnit unit,
     * BlockingQueue<Runnable> workQueue,    50
     * ThreadFactory threadFactory,
     * RejectedExecutionHandler handler
     * <p>
     * 150个线程进来
     * 1、先立即运行 8个
     * 2、接下来剩下任务进入队列  50 个 （下一步被人拿了8以后再进8）
     * 3、拿出8个，达到运行峰值 16 个
     * 4、状态。16个在运行，50个队列等待。最终只有 66个线程被安排了。
     * 5、150-66= 84个 要被RejectedExecutionHandler抛弃
     *
     * @return
     */
    //配置自己的业务线程池 核心业务线程池
    @Bean("corePool")
    public ThreadPoolExecutor executor(ThreadConfigProperties properties) {
        return new ThreadPoolExecutor(
                properties.core,
                properties.max,
                properties.keepalive, //线程池 1min了都没有活要干了
                TimeUnit.MILLISECONDS,
                new LinkedBlockingDeque<>(properties.queueLength),
                new MyItemServiceThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
    }

    // 从properties中获取参数
    @Component
    @ConfigurationProperties(prefix = "item-service.thread")
    @Data
    class ThreadConfigProperties {
        private Integer core;
        private Integer max;
        private Long keepalive;
        private Integer queueLength;
    }

    // 自定义线程工厂
    class MyItemServiceThreadFactory implements ThreadFactory {
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setName("item-service: "+ UUID.randomUUID().toString().substring(0,5));
            return thread;
        }
    }


}
